package ro.ulbsibiu.acaps.viewer.noc;

import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.io.File;
import java.io.FileNotFoundException;

import javax.swing.JFrame;
import javax.xml.bind.JAXBException;

import org.apache.log4j.Logger;
import org.jgraph.JGraph;
import org.jgraph.graph.VertexView;
import org.jgrapht.graph.AbstractGraph;

import ro.ulbsibiu.acaps.graph.noc.NocGraph;
import ro.ulbsibiu.acaps.viewer.layout.JGraphLayoutMorphingManager;
import ro.ulbsibiu.acaps.viewer.layout.JGraphLayoutPanel;

import com.jgraph.components.labels.MultiLineVertexRenderer;
import com.jgraph.layout.simple.SimpleGridLayout;

/**
 * @author cipi
 * 
 */
public class NocViewer {

	/** autogenerated serial version UID */
	private static final long serialVersionUID = 8532281998520203210L;

	/**
	 * Logger for this class
	 */
	private static final Logger logger = Logger
			.getLogger(NocViewer.class);

	private NocJGraphModelAdapter jgAdapter;

	private AbstractGraph<Object, Object> graph;

	private String mappingXmlFilePath;
	
	/** the number of nodes placed horizontally */
	private int hSize;

	public NocViewer(AbstractGraph<Object, Object> graph,
			String mappingXmlFilePath, int hSize) {
		logger.assertLog(graph != null, null);
		logger.assertLog(mappingXmlFilePath != null, null);

		this.graph = graph;
		this.mappingXmlFilePath = mappingXmlFilePath;
		this.hSize = hSize;
	}

	public JGraphLayoutPanel initialize() throws JAXBException {
		// create a visualization using JGraph, via an adapter
		jgAdapter = new NocJGraphModelAdapter(graph, new File(mappingXmlFilePath));
		JGraph jgraph = new JGraph(jgAdapter);

		// Overrides the global vertex renderer
		VertexView.renderer = new MultiLineVertexRenderer();
		// we hide the icon that indicates grouping (we create NoC node - core groups)
		jgraph.putClientProperty(MultiLineVertexRenderer.CLIENTPROPERTY_SHOWFOLDINGICONS, Boolean.FALSE);
		
		JGraphLayoutPanel layoutPanel = new JGraphLayoutPanel(jgraph) {

			@Override
			public void reset() {
				SimpleGridLayout simpleGridLayout = new SimpleGridLayout();
				simpleGridLayout.setNumCellsPerRow(hSize);
				simpleGridLayout.setActOnUnconnectedVerticesOnly(false);
				simpleGridLayout.setOrdered(true);
				execute(simpleGridLayout);
				graph.clearSelection();
				JGraphLayoutMorphingManager.fitViewport(graph);
			}
			
		};

		return layoutPanel;
	}

	public static void main(String[] args) throws FileNotFoundException, JAXBException {
		if (args == null || args.length < 2) {
			System.err
					.println("usage:   java NocApplicationMappingViewer.class {NoC topology} {mapping XML}");
			System.err
					.println("example: java NocApplicationMappingViewer.class ../NoC-XML/src/ro/ulbsibiu/acaps/noc/topology/mesh2D/4x4 ../CTG-XML/xml/VOPD/ctg-0/mapping-0_m_bb.xml");
		} else {
			NocGraph nocGraph = new NocGraph(args[0]);
			int hSize = 0;
			try {
				String hSizeAsString = args[0].substring(0, args[0].lastIndexOf("x"));
				hSizeAsString = hSizeAsString.substring(hSizeAsString.lastIndexOf("/") + 1);
				hSize = Integer.valueOf(hSizeAsString);
			} catch (Exception e) {
				logger.fatal("Could not determine hSize! Stopping...", e);
				System.exit(0);
			}
			NocViewer app = new NocViewer(nocGraph, args[1], hSize);

			// Switch off D3D because of Sun XOR painting bug
			// See http://www.jgraph.com/forum/viewtopic.php?t=4066
			System.setProperty("sun.java2d.d3d", "false");
			JFrame frame = new JFrame(
					"Network-on-Chip Application Mapping Viewer (" + args[0]
							+ " | " + args[1] + ")");
			final JGraphLayoutPanel layoutPanel = app.initialize();
			frame.getContentPane().add(layoutPanel);
			frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
			frame.addComponentListener(new ComponentAdapter() {

				@Override
				public void componentResized(ComponentEvent e) {
					layoutPanel.reset();
					super.componentResized(e);
				}
				
			});
			frame.pack();
			frame.setSize(800, 600);
			frame.setVisible(true);
		}
	}

}
